from typing import Optional, Union, List

import uvicorn
from fastapi import FastAPI,Cookie,Header,Response
from fastapi.openapi.docs import get_swagger_ui_html
from pydantic import BaseModel, Field
from starlette.staticfiles import StaticFiles

# 创建 FastAPI 应用实例，并把默认的/docs请求禁用
# debug表示是否开启调试模式，默认是False
app = FastAPI(docs_url=None,debug=True)
app.mount("/static", StaticFiles(directory="../static"), name="static")    # 静态文件

@app.get("/docs", include_in_schema=False)
def custom_swagger_ui():
    return get_swagger_ui_html(
        openapi_url = "/openapi.json",
        title = "Swagger UI for FastAPI",
        swagger_js_url="/static/swagger-ui-bundle.min.js",
        swagger_css_url="/static/swagger-ui.min.css"
    )

users = {
    "x": {"id": 0},
    "a": {"id": 1,"username": "a"},
    "b": {"id": 2,"username": "b","password": "bbb"},
    "c": {"id": 3,"username": "c","password": "ccc", "description": "default"},
    "d": {"id": 4,"username": "d","password": "ddd", "description": "user ddd"},
    "e": {"id": 5,"username": "e","password": "eee", "description": "user eee", "fullname": "Mary Water"},
}

# 定义一个响应模型
class UserOut(BaseModel):
    id: int = Field(...,examples=["用户id"])
    username: Optional[str] = Field(None,examples=["用户名"])
    password: str = Field(default="******",examples=["用户密码不返回"])
    description: Optional[str] = Field(None,examples=["用户描述"])
    fullname: Optional[str] = Field(None,examples=["用户全名"])

# 在url的定义中指定response_model参数，指定响应模型,这样我们的数据就与模型关联上了（要求输出的结果使用指定的模型规范）
# 响应模型定义成什么样子就会输出什么，会重新转换为要输出的内容，多余的字段会被过滤掉

# @app.get("/users/{username}",response_model=UserOut,response_model_include={"id","username"})   # 只输出指定的字段
# @app.get("/users/{username}",response_model=UserOut,response_model_exclude={"id","username"})   # 排除指定的字段
# @app.get("/users/{username}",response_model=UserOut,response_model_exclude_unset=True)      # 默认为False，对于使用默认值的字段不会在响应中返回
@app.get("/users/{username}",response_model=UserOut)
async def get_user(username:str):
    user = users.get(username,0)
    # 移除密码字段，因为此字段不响应返回
    user.pop("password")
    return user

@app.get("/users",response_model=List[UserOut])
async def get_users():
    # get_users 函数返回的是一个字典 users，但响应模型 List[UserOut] 期望的是一个列表。需要将字典的值转换为列表返回。
    users_list = list(users.values())
    # 把list中每一个元素中密码字段移除
    users_list = [{k: v for k, v in user.items() if k != "password"} for user in users_list]
    return users_list


if __name__ == '__main__':
    uvicorn.run("main:app", host="127.0.0.1", port=8008, reload=True)